/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.cratos.xxgramoss.base;

import com.cratos.xxgramoss.sys.RoleService;
import com.cratos.xxgramoss.sys.UserMember;
import java.io.*;
import java.util.*;
import javax.annotation.Resource;
import org.redkale.convert.*;
import org.redkale.convert.json.*;
import org.redkale.net.http.*;
import org.redkale.source.DataSource;
import org.redkale.util.*;

/**
 *
 * @author admin
 */
@WebServlet({"/dync/*"})
public final class DyncServlet extends BaseServlet {

    public static final class TextValue {

        public int value;

        public String text;

        public TextValue() {

        }

        public TextValue(int value, String text) {
            this.value = value;
            this.text = text;
        }
    }

    public static final class Menu {

        public int moduleid;

        public int actionid;

        public String text;
        
        public String webRouterKey;

        public String iconCls;

        public String state;

        public String url;

        public boolean hidden;
        // 是否开放菜单（无权限控制）
        public boolean dispark;

        public Menu[] children;

        public Menu copy() {
            Menu menu = new Menu();
            menu.moduleid = this.moduleid;
            menu.actionid = this.actionid;
            menu.text = this.text;
            menu.webRouterKey = this.webRouterKey;
            menu.iconCls = this.iconCls;
            menu.url = this.url;
            menu.hidden = this.hidden;
            menu.dispark = this.dispark;
            if (this.children != null) {
                Menu[] nodes = new Menu[this.children.length];
                for (int i = 0; i < nodes.length; i++) {
                    Menu m = this.children[i];
                    if (m != null) {
                        nodes[i] = m.copy();
                    }
                }
                menu.children = nodes;
            }
            return menu;
        }

        @Override
        public String toString() {
            return "Menu{moduleid=" + moduleid + ", actionid=" + actionid + ", text=" + text + ", webRouterKey=" + webRouterKey  + ", iconCls=" + iconCls + ", state=" + state
                    + ", url=" + url + ", hidden=" + hidden + ", dispark=" + dispark + ", children=" + (children == null ? null : Arrays.toString(children)) + '}';
        }

        public boolean isLeaf() {
            return children == null || children.length == 0;
        }

        // 获取真正的actionid
        private int getRealActionid() {
            int realActionid = this.actionid;
            if (realActionid > 100000) {    // 6位数的actionid是4位原始actionid + 2位序号，所以要取前四位
                realActionid = realActionid / 100;
            }
            return realActionid;
        }

        public boolean contains(Set<Integer> ids) {
            if (isLeaf()) {
                return this.moduleid < 1 || ids.contains(this.moduleid) || this.dispark;
            }
            for (Menu menu : this.children) {
                if (menu.contains(ids) || menu.dispark) {
                    return true;
                }
            }
            return false;
        }

        public Menu trim(final Set<Integer> ids, final Set<Integer> options) {
            if (!this.isLeaf()) {
                boolean childrenEmpty = true;
                if (this.children != null && this.children.length > 0) {
                    Menu[] newchilds = new Menu[this.children.length];
                    int index = 0;
                    for (int i = 0; i < this.children.length; i++) {
                        Menu m = this.children[i].trim(ids, options);
                        if (m != null) {
                            newchilds[index++] = m;
                        }
                    }
                    childrenEmpty = index == 0;
                    if (index > 0 && index < newchilds.length) {
                        Menu[] tmps = new Menu[index];
                        System.arraycopy(newchilds, 0, tmps, 0, index);
                        this.children = tmps;
                    }
                }
                if (!childrenEmpty) {
                    return this;
                }
                return null;
            }
            if (this.dispark) { // 开放式菜单，不需要校验权限
                return this;
            }
            if (this.actionid == 0) {  // 未配置actionid，只根据moculeidp
                return (this.moduleid < 1 || ids.contains(this.moduleid)) ? this : null;
            }
            // 如果有配置actionid，则用moduleid和actionid联合确定权限
            return (options.contains(this.moduleid * 10000 + this.getRealActionid())) ? this : null;
        }
    }

    private final List<Menu> menus = new ArrayList<>();

    @Resource
    private RoleService roleService;

    @Resource(name = "oss")
    protected DataSource source;
    
    @Resource(name = "APP_HOME")
    private File home;

    public DyncServlet() {
        try {
            Encodeable encoder1 = JsonFactory.root().loadEncoder(MemberInfo.class);
            Encodeable encoder2 = JsonFactory.root().loadEncoder(UserMember.class);
            JsonFactory.root().registerSkipAllIgnore(true);
            //屏蔽掉 password 字段
            JsonFactory.root().register(MemberInfo.class, encoder1);
            JsonFactory.root().register(UserMember.class, encoder2);
            //-------------------------------------------------------------------------------
            String path = "/" + DyncServlet.class.getPackage().getName().replace('.', '/') + "/sysmenus.json";
            try (InputStream in = DyncServlet.class.getResourceAsStream(path)) {
                List<Menu> list = JsonConvert.root().convertFrom(new TypeToken<List<Menu>>() {
                }.getType(), Utility.read(in));
                menus.addAll(list);
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    @Override
    public void init(HttpContext context, AnyValue conf) {
        try {
            // 加载平台模块的菜单
            File platfMenusFile = new File(home, "conf/menus.json");
            //-------------------------------------------------------------------------------
            if (platfMenusFile.isFile() && platfMenusFile.canRead()) {
                try (InputStream in = new FileInputStream(platfMenusFile)) {
                    List<Menu> list = JsonConvert.root().convertFrom(new TypeToken<List<Menu>>() {
                    }.getType(), Utility.read(in));
                    menus.addAll(list);
                }
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    public Map<String,Object> datas(HttpRequest req, HttpResponse resp) throws IOException {
        resp.setContentType("text/javascript; charset=utf-8");
        MemberInfo user = req.currentUser();
        String userjson;
        String menujson;
        List<Menu> menuslist = new ArrayList<>();
        Map<String, Object> map = new HashMap<>();
        if (user == null) {
            userjson = "{}";
            menujson = "[]";
        } else {
            userjson = convert.convertTo(user);
            if (user.canAdmin()) {
                menujson = convert.convertTo(menus);
                menuslist = menus;
            } else {
                Set<Integer> options = new HashSet<>();
                Set<Integer> modules = new HashSet<>();
                if (user.getOptions() != null) {
                    for (int m : user.getOptions()) {
                        options.add(m);
                        int v = m / 10000;
                        if (v > 0) {
                            modules.add(v);
                        }
                    }
                }

                List<Menu> ms = new ArrayList<>();
                for (Menu m : menus) {
                    if (m.contains(modules) || m.dispark) {
                        Menu trimMenu = m.copy().trim(modules, options);
                        if (trimMenu != null) {
                            ms.add(trimMenu);
                        }
                    }
                }
                menujson = convert.convertTo(ms);
                menuslist = ms;
            }
        }
        map.put("userjson",userjson);
        map.put("menujson",menujson);
        map.put("user",user);
        map.put("menuslist",menuslist);
        return map;
    }
    
    @HttpMapping(url = "/dync/mydata", auth = false)
    public void vuedata(HttpRequest req, HttpResponse resp) throws IOException {
        Map map =datas(req,resp);
        Map<String, Object> json = new HashMap<>();
        json.put("system_adminpid", MemberInfo.TYPE_ADMIN);
        json.put("system_sysmenus", map.get("menuslist"));
        json.put("system_memberinfo", map.get("user"));
        json.put("system_rmodules", roleService.queryModuleInfo());
        json.put("system_actiones", roleService.queryActionInfo());
        resp.finish(json);
    }
}
